package com.avalon.core.select.builder;

import com.avalon.core.condition.Condition;
import com.avalon.core.model.FieldValueStatement;
import com.avalon.core.select.*;
import com.avalon.core.service.AbstractService;
import com.avalon.core.util.ObjectUtils;
import lombok.Data;

import java.util.List;

@Data
public class SelectBuilder {
    private TableFieldSectionList tableFieldSectionList;
    private ConditionFieldList conditionFieldList;
    private OrderFieldList orderFieldList;

    public Boolean getDistinct() {
        return isDistinct;
    }

    public void setDistinct(Boolean distinct) {
        isDistinct = distinct;
    }

    private Boolean isDistinct = false;//是否去重

    public TableFieldSectionList getTableFieldSectionList() {
        return tableFieldSectionList;
    }

    protected void setTableFieldSectionList(TableFieldSectionList tableFieldSectionList) {
        this.tableFieldSectionList = tableFieldSectionList;
    }

    public ConditionFieldList getConditionFieldList() {
        return conditionFieldList;
    }

    protected void setConditionFieldList(ConditionFieldList conditionFieldList) {
        this.conditionFieldList = conditionFieldList;
    }

    public OrderFieldList getOrderFieldList() {
        return orderFieldList;
    }

    protected void setOrderFieldList(OrderFieldList orderFieldList) {
        this.orderFieldList = orderFieldList;
    }

    public SelectAliasSupport getAliasSupport() {
        return aliasSupport;
    }

    protected void setAliasSupport(SelectAliasSupport aliasSupport) {
        this.aliasSupport = aliasSupport;
    }

    protected void setService(AbstractService service) {
        this.service = service;
    }

    protected void setFieldValueStatement(FieldValueStatement fieldValueStatement) {
        this.fieldValueStatement = fieldValueStatement;
    }

    private SelectAliasSupport aliasSupport;
    private AbstractService service;
    private FieldValueStatement fieldValueStatement;


    public FieldValueStatement getFieldValueStatement() {
        return fieldValueStatement;
    }


    public AbstractService getService() {
        return service;
    }


    /**
     * 获取查询条件的表别名
     *
     * @param condition
     * @return
     */
    public String getConditionAlias(Condition condition) {
        return tableFieldSectionList.getConditionAlias(condition, aliasSupport);
    }

    public String getOrderAlias(String fieldName) {
        return tableFieldSectionList.getOrderAlias(fieldName, aliasSupport);
    }

    /**
     * 获取多级表之前的表别名
     *
     * @param prefixTable
     * @return
     */
    public String getPrefixTableAlias(String prefixTable) {
        return tableFieldSectionList.getPrefixTableAlias(prefixTable, aliasSupport);
    }

    /**
     * 获取别名之后的字段名
     *
     * @param fieldName
     * @return
     */
    public SelectionField getField(String fieldName) {
        return tableFieldSectionList.getField(fieldName, aliasSupport);
    }


    protected SelectBuilder() {

    }

    public SelectBuilder(AbstractService service) {
        this.tableFieldSectionList = new TableFieldSectionList();
        this.conditionFieldList = new ConditionFieldList();
        this.orderFieldList = new OrderFieldList();
        this.aliasSupport = new SelectAliasSupport();
        this.service = service;
        this.fieldValueStatement = new FieldValueStatement();
    }

    public void addField(String field) {
        tableFieldSectionList.addField(field, service);
    }

    public void addOrder(String field, String order) {
        OrderField orderField = orderFieldList.addOrder(field, order, service);
        tableFieldSectionList.addOrder(orderField, service);
    }

    public void addCondition(Condition condition) {
        conditionFieldList.addCondition(condition, service);
        List<Condition> flatConditions = condition.getFlatConditions();
        for (Condition flatCondition : flatConditions) {
            tableFieldSectionList.addCondition(
                    new ConditionField(flatCondition.getName(), condition, service),
                    service);
        }
    }

    /**
     * 获取全部记录sql语句
     *
     * @return
     */
    protected StringBuilder getAllSql() {
        if (orderFieldList.size() == 0) {
            orderFieldList.addOrder("id", "desc", service);
        }
        tableFieldSectionList.completeTable();
        this.getFieldValueStatement().clear();
        StringBuilder sql = new StringBuilder();
        sql.append(" SELECT ");
        if (ObjectUtils.isNotNull(getDistinct()) && getDistinct()) {
            sql.append("DISTINCT ");
        }
        int count = 0;
        for (TableFieldSection tableFieldSection : tableFieldSectionList) {
            StringBuilder fieldSql = tableFieldSection.getFieldSql(aliasSupport);
            if (!fieldSql.isEmpty()) {
                if (count > 0) {
                    sql.append(",");
                }
                sql.append(fieldSql);
                count++;
            }
        }
        sql.append(" FROM ");
        sql.append(service.getServiceTableName());
        sql.append(" ");
        sql.append(service.getAlias(aliasSupport));
        for (TableFieldSection tableFieldSection : tableFieldSectionList) {
            StringBuilder tableSql = tableFieldSection.getTableSql(aliasSupport, this);
            if (!tableSql.isEmpty()) {
                sql.append(tableSql);
            }
        }
        if (conditionFieldList.size() > 0) {
            sql.append(" WHERE ");
            sql.append(conditionFieldList.getConditionSql(this));
        }

        if (orderFieldList.size() > 0) {
            sql.append(" ORDER BY ");
            sql.append(orderFieldList.getOrderSql(this));
        }

        return sql;
    }

    /**
     * 获取当前查询sql语句
     */
    public StringBuilder getSql() {
        return getAllSql();
    }

    /**
     * 获取sum sql语句
     *
     * @return
     */
    public StringBuilder getSumSql() {
        StringBuilder sb = new StringBuilder();
        StringBuilder allSql = getSql();
        StringBuilder sumField = new StringBuilder();
        for (TableFieldSection tableFieldSection : tableFieldSectionList) {
            sumField = tableFieldSection.getFieldAliasSql(aliasSupport);
            if (!sumField.isEmpty()) {
                break;
            }
        }
        sb.append("SELECT ");

        sb.append("SUM(`");
        sb.append(sumField.toString());
        sb.append("`)");
        sb.append(" AS '").append(sumField).append("'");
        sb.append(" FROM( ");
        sb.append(allSql);
        sb.append(")");
        sb.append(" AS ZX");
        return sb;

    }

    /**
     * 获取个数的sql语句
     *
     * @return
     */
    public StringBuilder getCountSql() {
        StringBuilder sb = new StringBuilder();
        sb.append("SELECT ");
        sb.append("COUNT(*)");
        sb.append(" FROM( ");
        sb.append(getSql());
        sb.append(")");
        sb.append(" AS ZX");
        return sb;
    }

}
